# 继承是必要条件，子类重写父类方法，定义函数时，使用的是父类，
# 但是实际是可以传字类对象作为参数；因此实际调用的方法取决于对象类型

class Animal:
    def run(self):
        print('Animal is running...')


class Dog(Animal):
    def run(self):
        print('Dog is running...')


class Cat(Animal):
    def run(self):
        print('Cat is running...')


def run_animal(animal):
    animal.run()


cat = Cat()
dog = Dog()

run_animal(dog)
run_animal(cat)


# isinstance() 函数来判断一个对象是否是一个已知的类型
print(isinstance(cat, Cat))     # True
print(isinstance(cat, Animal))  # True
print(isinstance(dog, Dog))     # True
print(isinstance(dog, Animal))  # True
print(isinstance(cat, Dog))     # False

# 如果在当前模块启动程序，打印的类为<class '__main__.Cat'>
# 如果在其他模块导入该类，打印的类为<class '模块名.Cat'>
# 其实就是 __name__.类名,因为__name__如果在当前模块启动，就是__main__,在其他模块导入，就是模块名
print(type(cat))
print(type(123))
print(type('abc'))